package com.restphp.java.utils.http.client;

import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * Created by sofical on 2020/7/13.
 */
final public class HttpClientUtils {
    /**
     * 请求远程地址内容.
     * @param url 远程地址.
     * @param request 请求数据.
     * @param method 请求方法.
     * @param headerMap 头信息.
     * @return 请求结果.
     */
    public static ClientResponse request (String url, String request, String method, Map<String, String> headerMap) {
        return request(url, request, method, headerMap, "utf-8");
    }

    /**
     * 请求远程地址内容.
     * @param url 远程地址.
     * @param request 请求数据.
     * @param method 请求方法
     * @param headerMap 头信息.
     * @param charset 编码.
     * @return 请求结果.
     */
    public static ClientResponse request (String url, String request, String method, Map<String, String> headerMap, String charset) {
        HttpURLConnection con = null;
        try {
            TrustManager[] tm = {new MyX509TrustManager ()};
            SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslsession) {
                    System.out.println("WARNING: Hostname is not matched for cert.");
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

            URL u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            con.setUseCaches(false);
            if (null != headerMap) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    con.setRequestProperty(entry.getKey(), entry.getValue().trim());
                }
            }
            con.setRequestMethod(method);
            con.setRequestProperty("Charset", charset);
            if (!"GET".equals(method) && !"DELETE".equals(method) && null!=request) {
                con.setDoInput(true);
                con.setDoOutput(true);
                OutputStream os = con.getOutputStream();
                os.write(request.getBytes(charset));
                os.flush();
                os.close();
            }

            int status = con.getResponseCode();

            StringBuilder sb = new StringBuilder(con.getContentLength() == -1 ? 1024 * 5 : con.getContentLength());

            ClientResponse response = new ClientResponse();
            response.setStatus(status);
            if (status >= HttpURLConnection.HTTP_OK
                    && status < HttpURLConnection.HTTP_MULT_CHOICE) {
                BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), charset));
                for (String line = br.readLine(); line != null; line = br.readLine()) {
                    sb.append(line);
                }
            } else {
                BufferedReader br = new BufferedReader(new InputStreamReader(con.getErrorStream(), charset));
                for (String line = br.readLine(); line != null; line = br.readLine()) {
                    sb.append(line);
                }
            }

            response.setBody(sb.toString());

            return response;
        } catch (Exception e) {
            throw new RuntimeException("请求接口失败：" + e.getMessage());
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }
    }
}
